import React, { Component } from 'react';
import './List.scss'
import Spinner from '../Spinner';

class ScrollView extends Component {
    constructor(props) {
        super(props)
        this.state = { /* 初始化 Data */
            list: [],
            loading: false
        }
    }

    // 存储当前滚动的node节点容器
    node = null

    // 得到 派生的 state 从 props 中
    // 这个生命周期用于，在初始化和更新阶段，接受父组件的 props 数据
    // 可以对 props 进行格式化，过滤等操作，返回值将作为新的 state 合并到 state 中

    // 只要组件更新，就会执行 getDerivedStateFromProps
    // 不管是 props 改变，还是 setState ，或是 forceUpdate
    static getDerivedStateFromProps(newProps) {
        // 取出父节点中的 data 合并到state，并返回给 componentDidUpdate 参数三
        // 也就是说在这个阶段，不需要手动 setState赋值，也可以合并state
        const { data } = newProps
        return { list: data.list || [] }
    }

    /* 获取更新后容器高度 */
    componentDidUpdate(prevProps, prevState, snapshot) {
        // console.log('scrollView容器高度变化:', this.node.scrollHeight - snapshot)
        // snapshot 是 getDerivedStateFromProps 中返回的数据
    }

    // 父组件重新render后执行 性能优化 只有两次数据完全不同的时候 才会触发render渲染
    // 加入loading后 需要多状态，所以放弃
    shouldComponentUpdate(newProps, newState) {
        return (newState.list !== this.state.list) || (newProps.loading !== this.props.loading)
    }

    // 获取commit更新前的快照 
    getSnapshotBeforeUpdate(preProps, preState, ...args) {
        // console.log('commit阶段执行 ===> ', preProps, preState, ...args)
        // 返回的值可以给 componentDidUpdate 的第三个参数使用， 因为那里能拿到最新的props和state值
        return {
            name: 'zhangsan'
        }
    }
    // commit更新后的生命周期
    componentDidUpdate(prevProps, prevState, snapshot) {
        // console.log('snapshot ==========> ', snapshot)
    }

    // render commit结束，设置滚动监听
    componentDidMount() {
        // console.log('this.node ===> ', this.node)
        this.node.addEventListener('scroll', this.handerScroll)
    }

    // 组件卸载 清除副作用
    componentWillUnmount() {
        this.node.removeEventListener('scroll', this.handerScroll)
    }

    // 控制滚动条滚动
    handerScroll = (e) => {
        const { scroll } = this.props
        scroll && scroll(e)
        this.handerScrolltolower()
    }
    // 判断滚动条是否滚动到底部
    handerScrolltolower() {
        const { scrolltolower, loading } = this.props
        const { scrollHeight, scrollTop, offsetHeight } = this.node
        // 到达容器底部位置 并且没有在加载中
        if (!loading && scrollHeight <= scrollTop + offsetHeight) {
            scrolltolower && scrolltolower()
            console.log('滚动到了底部')
        }
    }

    render() {
        const { list } = this.state
        const { component, loading, height, className, loadMoreText } = this.props
        return (
            <div style={{
                height: height || '500px',
                overflow: 'scroll'
            }}
                className={`listBoxClass  ${className}`}
                ref={(node) => this.node = node}>
                <div>
                    {
                        list.map((item, key) => (
                            React.createElement(component, { item, key })
                        ))
                    }
                    {
                        loading && <div className="listMore">
                            <Spinner size={20} />  <span className='FooterMoreText'>{loadMoreText || '加载中...'}</span>
                        </div>
                    }
                </div>
            </div>
        );
    }
}

export default ScrollView;
